/**
 * @file gameservicediscovery.h
 * @brief 游戏服务发现类头文件 - 用于发现和管理游戏服务
 *
 * GameServiceDiscovery类提供与API Gateway服务发现API的集成，支持：
 * - 按游戏类型筛选服务列表
 * - 健康状态检查和筛选
 * - 自动刷新机制
 * - 完善的错误处理和重试机制
 */

#ifndef GAMESERVICEDISCOVERY_H
#define GAMESERVICEDISCOVERY_H

#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QTimer>
#include <QUrl>
#include <QUrlQuery>
#include <QStringList>

/**
 * @struct GameServiceInfo
 * @brief 游戏服务信息结构体
 *
 * 包含从服务发现API获取的完整服务信息
 */
struct GameServiceInfo {
    QString serviceName;          ///< 服务名称
    QString serviceVersion;       ///< 服务版本
    QString host;                 ///< 主机地址
    int port;                     ///< 端口号
    QString healthCheckEndpoint;  ///< 健康检查端点
    QStringList endpoints;        ///< 支持的API端点列表
    QString lastHeartbeat;        ///< 最后心跳时间
    bool healthy;                 ///< 健康状态
    int weight;                   ///< 负载权重
    QJsonObject metadata;         ///< 元数据信息
    
    // 便捷访问方法
    QString gameType() const {
        // 首先尝试从元数据获取
        QString metaGameType = metadata["game_type"].toString();
        if (!metaGameType.isEmpty()) {
            return metaGameType;
        }

        // 如果元数据中没有，从服务名称推断
        QString name = serviceName.toLower();
        if (name.contains("snake")) {
            return "snake";
        } else if (name.contains("tetris")) {
            return "tetris";
        } else if (name.contains("puzzle")) {
            return "puzzle";
        }

        // 默认返回空字符串
        return "";
    }
    int maxPlayers() const { return metadata["max_players"].toString().toInt(); }
    QString region() const { return metadata["region"].toString(); }
    QString version() const { return metadata["version"].toString(); }
    
    // 生成唯一标识符
    QString uniqueId() const { return QString("%1:%2:%3").arg(serviceName, host).arg(port); }
    
    // 生成显示名称
    QString displayName() const {
        QString regionStr = region().isEmpty() ? "默认" : region();
        return QString("%1 (%2:%3) - %4区域").arg(serviceName, host).arg(port).arg(regionStr);
    }
};

/**
 * @class GameServiceDiscovery
 * @brief 游戏服务发现类
 *
 * 提供与API Gateway服务发现API的完整集成，支持：
 * - 多种筛选条件（游戏类型、服务名称、健康状态）
 * - 自动刷新和缓存机制
 * - 网络错误处理和重试
 * - 异步信号槽通信
 */
class GameServiceDiscovery : public QObject {
    Q_OBJECT

public:
    /**
     * @brief 构造函数
     * @param apiGatewayUrl API Gateway的基础URL
     * @param parent 父对象指针
     */
    explicit GameServiceDiscovery(const QString& apiGatewayUrl, QObject* parent = nullptr);

    // === 主要API方法 ===
    /**
     * @brief 按游戏类型获取服务列表
     * @param gameType 游戏类型（snake、tetris等）
     * @param healthyOnly 是否只返回健康的服务
     */
    void getServicesByGameType(const QString& gameType, bool healthyOnly = true);
    
    /**
     * @brief 获取所有服务
     * @param healthyOnly 是否只返回健康的服务
     */
    void getAllServices(bool healthyOnly = true);
    
    /**
     * @brief 按服务名称获取服务列表
     * @param serviceName 服务名称
     * @param healthyOnly 是否只返回健康的服务
     */
    void getServicesByName(const QString& serviceName, bool healthyOnly = true);
    
    // === 自动刷新控制 ===
    /**
     * @brief 设置自动刷新间隔
     * @param seconds 刷新间隔（秒）
     */
    void setAutoRefreshInterval(int seconds);
    
    /**
     * @brief 启动自动刷新
     */
    void startAutoRefresh();
    
    /**
     * @brief 停止自动刷新
     */
    void stopAutoRefresh();
    
    // === 工具方法 ===
    /**
     * @brief 手动刷新当前查询
     */
    void refreshCurrentQuery();
    
    /**
     * @brief 获取支持的游戏类型列表
     * @return 游戏类型列表
     */
    QStringList getSupportedGameTypes() const;
    
    /**
     * @brief 检查服务是否可用
     * @param service 服务信息
     * @return 是否可用
     */
    bool isServiceAvailable(const GameServiceInfo& service) const;

signals:
    /**
     * @brief 服务列表接收成功信号
     * @param services 服务列表
     * @param gameType 查询的游戏类型（如果按类型查询）
     * @param queryInfo 查询信息（包含筛选条件）
     */
    void servicesReceived(const QList<GameServiceInfo>& services, const QString& gameType, const QJsonObject& queryInfo);
    
    /**
     * @brief API错误信号
     * @param error 错误信息
     * @param errorCode 错误代码
     */
    void errorOccurred(const QString& error, const QString& errorCode);
    
    /**
     * @brief 网络错误信号
     * @param error 网络错误信息
     */
    void networkError(const QString& error);
    
    /**
     * @brief 服务发现开始信号
     * @param queryType 查询类型描述
     */
    void discoveryStarted(const QString& queryType);

private slots:
    /**
     * @brief 处理网络响应
     */
    void handleNetworkReply();
    
    /**
     * @brief 自动刷新槽函数
     */
    void refreshServices();

private:
    // === 内部方法 ===
    /**
     * @brief 发起HTTP请求
     * @param gameType 游戏类型（可选）
     * @param serviceName 服务名称（可选）
     * @param healthyOnly 是否只返回健康的服务
     */
    void makeRequest(const QString& gameType = "", const QString& serviceName = "", bool healthyOnly = true);
    
    /**
     * @brief 解析服务响应
     * @param response API响应JSON对象
     * @return 解析后的服务列表
     */
    QList<GameServiceInfo> parseServicesResponse(const QJsonObject& response);
    
    /**
     * @brief 解析单个服务信息
     * @param serviceObj 服务JSON对象
     * @return 解析后的服务信息
     */
    GameServiceInfo parseServiceInfo(const QJsonObject& serviceObj);
    
    /**
     * @brief 验证服务信息有效性
     * @param service 服务信息
     * @return 是否有效
     */
    bool validateServiceInfo(const GameServiceInfo& service) const;

    /**
     * @brief 判断是否为游戏服务
     * @param service 服务信息
     * @return 是否为游戏服务
     */
    bool isGameService(const GameServiceInfo& service) const;

    /**
     * @brief 生成查询描述
     * @param gameType 游戏类型
     * @param serviceName 服务名称
     * @param healthyOnly 是否只查询健康服务
     * @return 查询描述字符串
     */
    QString generateQueryDescription(const QString& gameType, const QString& serviceName, bool healthyOnly) const;

    // === 成员变量 ===
    QNetworkAccessManager* m_networkManager;   ///< 网络访问管理器
    QString m_apiGatewayUrl;                    ///< API Gateway URL
    QTimer* m_refreshTimer;                     ///< 自动刷新定时器
    
    // 当前查询状态
    QString m_currentGameType;                  ///< 当前查询的游戏类型
    QString m_currentServiceName;               ///< 当前查询的服务名称
    bool m_currentHealthyOnly;                  ///< 当前是否只查询健康服务
    
    // 缓存和配置
    QStringList m_supportedGameTypes;           ///< 支持的游戏类型列表
    int m_requestTimeout;                       ///< 请求超时时间（毫秒）
    bool m_isQueryInProgress;                   ///< 是否有查询正在进行
};

#endif // GAMESERVICEDISCOVERY_H

